home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevpcfb.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  23.5 KB  |  934 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevpcfb.c,v 1.2 2000/09/19 19:00:15 lpd Exp $ */
  20. /* IBM PC frame buffer (EGA/VGA) drivers */
  21. #include "memory_.h"
  22. #include "gconfigv.h"        /* for USE_ASM */
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gsparam.h"
  26. #include "gxdevice.h"
  27. #include "gdevpccm.h"
  28. #include "gdevpcfb.h"
  29.  
  30. /* We may compile this in a non-segmented environment.... */
  31. #ifndef _ss
  32. #define _ss
  33. #endif
  34.  
  35. /* Macro for casting gx_device argument */
  36. #define fb_dev ((gx_device_ega *)dev)
  37.  
  38. /* Procedure record */
  39. private dev_proc_map_rgb_color(ega0_map_rgb_color);
  40. private dev_proc_map_rgb_color(ega1_map_rgb_color);
  41. #define ega2_map_rgb_color pc_4bit_map_rgb_color
  42. private dev_proc_map_color_rgb(ega01_map_color_rgb);
  43. #define ega2_map_color_rgb pc_4bit_map_color_rgb
  44. #if ega_bits_of_color == 0
  45. #   define ega_map_rgb_color ega0_map_rgb_color
  46. #   define ega_map_color_rgb ega01_map_color_rgb
  47. #else
  48. # if ega_bits_of_color == 1
  49. #   define ega_map_rgb_color ega1_map_rgb_color
  50. #   define ega_map_color_rgb ega01_map_color_rgb
  51. # else
  52. #   define ega_map_rgb_color ega2_map_rgb_color
  53. #   define ega_map_color_rgb ega2_map_color_rgb
  54. # endif
  55. #endif
  56. #define ega_std_procs(get_params, put_params)\
  57.     ega_open,\
  58.     NULL,            /* get_initial_matrix */\
  59.     NULL,            /* sync_output */\
  60.     NULL,            /* output_page */\
  61.     ega_close,\
  62.     ega_map_rgb_color,\
  63.     ega_map_color_rgb,\
  64.     ega_fill_rectangle,\
  65.     ega_tile_rectangle,\
  66.     ega_copy_mono,\
  67.     ega_copy_color,\
  68.     NULL,            /* draw_line */\
  69.     ega_get_bits,\
  70.     get_params,\
  71.     put_params,\
  72.     NULL,            /* map_cmyk_color */\
  73.     NULL,            /* get_xfont_procs */\
  74.     NULL,            /* get_xfont_device */\
  75.     NULL,            /* map_rgb_alpha_color */\
  76.     gx_page_device_get_page_device
  77.  
  78. private const gx_device_procs ega_procs =
  79. {
  80.     ega_std_procs(NULL, NULL)
  81. };
  82.  
  83. private dev_proc_get_params(svga16_get_params);
  84. private dev_proc_put_params(svga16_put_params);
  85. private const gx_device_procs svga16_procs =
  86. {
  87.     ega_std_procs(svga16_get_params, svga16_put_params)
  88. };
  89.  
  90. /* All the known instances */
  91.         /* EGA */
  92. gx_device_ega far_data gs_ega_device =
  93. ega_device("ega", ega_procs, 80, 350, 48.0 / 35.0, 0x10);
  94.  
  95.         /* VGA */
  96. gx_device_ega far_data gs_vga_device =
  97. ega_device("vga", ega_procs, 80, 480, 1.0, 0x12);
  98.  
  99.         /* Generic SuperVGA, 800x600, 16-color mode */
  100. gx_device_ega far_data gs_svga16_device =
  101. ega_device("svga16", svga16_procs, 100, 600, 1.0, 0x29 /*Tseng */ );
  102.  
  103. /* Save the BIOS state */
  104. private pcfb_bios_state pcfb_save_state =
  105. {-1};
  106.  
  107. /* Initialize the EGA for graphics mode */
  108. int
  109. ega_open(gx_device * dev)
  110. {                /* Adjust the device resolution. */
  111.     /* This is a hack, pending refactoring of the put_params machinery. */
  112.     switch (fb_dev->video_mode) {
  113.     case 0x10:        /* EGA */
  114.         gx_device_adjust_resolution(dev, 640, 350, 1);
  115.         break;
  116.     case 0x12:        /* VGA */
  117.         gx_device_adjust_resolution(dev, 640, 480, 1);
  118.         break;
  119.     default:        /* 800x600 SuperVGA */
  120.         gx_device_adjust_resolution(dev, 800, 600, 1);
  121.         break;
  122.     }
  123.     if (pcfb_save_state.display_mode < 0)
  124.     pcfb_get_state(&pcfb_save_state);
  125.     /* Do implementation-specific initialization */
  126.     pcfb_set_signals(dev);
  127.     pcfb_set_mode(fb_dev->video_mode);
  128.     set_s_map(-1);        /* enable all maps */
  129.     return 0;
  130. }
  131.  
  132. /* Reinitialize the EGA for text mode */
  133. int
  134. ega_close(gx_device * dev)
  135. {
  136.     if (pcfb_save_state.display_mode >= 0)
  137.     pcfb_set_state(&pcfb_save_state);
  138.     return 0;
  139. }
  140.  
  141. /* Get/put the display mode parameter. */
  142. private int
  143. svga16_get_params(gx_device * dev, gs_param_list * plist)
  144. {
  145.     int code = gx_default_get_params(dev, plist);
  146.  
  147.     if (code < 0)
  148.     return code;
  149.     return param_write_int(plist, "DisplayMode", &fb_dev->video_mode);
  150. }
  151. private int
  152. svga16_put_params(gx_device * dev, gs_param_list * plist)
  153. {
  154.     int ecode = 0;
  155.     int code;
  156.     int imode = fb_dev->video_mode;
  157.     const char *param_name;
  158.  
  159.     switch (code = param_read_int(plist, (param_name = "DisplayMode"), &imode)) {
  160.     default:
  161.         ecode = code;
  162.         param_signal_error(plist, param_name, ecode);
  163.     case 0:
  164.     case 1:
  165.         break;
  166.     }
  167.  
  168.     if (ecode < 0)
  169.     return ecode;
  170.     code = gx_default_put_params(dev, plist);
  171.     if (code < 0)
  172.     return code;
  173.  
  174.     if (imode != fb_dev->video_mode) {
  175.     if (dev->is_open)
  176.         gs_closedevice(dev);
  177.     fb_dev->video_mode = imode;
  178.     }
  179.     return 0;
  180. }
  181.  
  182. /* Map a r-g-b color to an EGA color code. */
  183. #define Nb gx_color_value_bits
  184. private gx_color_index
  185. ega0_map_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
  186.            gx_color_value b)
  187. {
  188.     return pc_4bit_map_rgb_color(dev, r, r, r);
  189. }
  190. private gx_color_index
  191. ega1_map_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
  192.            gx_color_value b)
  193. {
  194. #define cvtop (gx_color_value)(1 << (Nb - 1))
  195.     return pc_4bit_map_rgb_color(dev, r & cvtop, g & cvtop, b & cvtop);
  196. }
  197. #undef Nb
  198.  
  199. /* Map a color code to r-g-b. */
  200. #define icolor (int)color
  201. private int
  202. ega01_map_color_rgb(gx_device * dev, gx_color_index color,
  203.             gx_color_value prgb[3])
  204. {
  205. #define one (gx_max_color_value / 2 + 1)
  206.     prgb[0] = (icolor & 4 ? one : 0);
  207.     prgb[1] = (icolor & 2 ? one : 0);
  208.     prgb[2] = (icolor & 1 ? one : 0);
  209.     return 0;
  210. #undef one
  211. }
  212. #undef icolor
  213.  
  214. /* ------ Internal routines ------ */
  215.  
  216. /* Structure for operation parameters. */
  217. /* Note that this structure is known to assembly code. */
  218. /* Not all parameters are used for every operation. */
  219. typedef struct rop_params_s {
  220.     fb_ptr dest;        /* pointer to frame buffer */
  221.     int draster;        /* raster of frame buffer */
  222.     const byte *src;        /* pointer to source data */
  223.     int sraster;        /* source raster */
  224.     int width;            /* width in bytes */
  225.     int height;            /* height in scan lines */
  226.     int shift;            /* amount to right shift source */
  227.     int invert;            /* 0 or -1 to invert source */
  228.     int data;            /* data for fill */
  229. } rop_params;
  230. typedef rop_params _ss *rop_ptr;
  231.  
  232. /* Assembly language routines */
  233.  
  234. #if USE_ASM
  235. void memsetcol(P1(rop_ptr));    /* dest, draster, height, data */
  236. #else
  237. #define memsetcol cmemsetcol
  238. private void
  239. cmemsetcol(rop_ptr rop)
  240. {
  241.     byte *addr = rop->dest;
  242.     int yc = rop->height;
  243.     byte data = rop->data;
  244.     int draster = rop->draster;
  245.  
  246.     while (yc--) {
  247.     byte_discard(*addr);
  248.     *addr = data;
  249.     addr += draster;
  250.     }
  251. }
  252. #endif
  253.  
  254. #if USE_ASM
  255. void memsetrect(P1(rop_ptr));    /* dest, draster, width, height, data */
  256. #else
  257. #define memsetrect cmemsetrect
  258. private void
  259. cmemsetrect(rop_ptr rop)
  260. {
  261.     int yc = rop->height;
  262.     int width = rop->width;
  263.  
  264.     if (yc <= 0 || width <= 0)
  265.     return;
  266.     {
  267.     byte *addr = rop->dest;
  268.     byte data = rop->data;
  269.  
  270.     if (width > 5) {    /* use memset */
  271.         int skip = rop->draster;
  272.  
  273.         do {
  274.         memset(addr, data, width);
  275.         addr += skip;
  276.         }
  277.         while (--yc);
  278.     } else {        /* avoid the fixed overhead */
  279.         int skip = rop->draster - width;
  280.  
  281.         do {
  282.         int cnt = width;
  283.  
  284.         do {
  285.             *addr++ = data;
  286.         } while (--cnt);
  287.         addr += skip;
  288.         }
  289.         while (--yc);
  290.     }
  291.     }
  292. }
  293. #endif
  294.  
  295. #if USE_ASM
  296. void memrwcol(P1(rop_ptr));    /* dest, draster, src, sraster, height, shift, invert */
  297. #  define memrwcol0(rop) memrwcol(rop)    /* same except shift = 0 */
  298. #else
  299. #  define memrwcol cmemrwcol
  300. #  define memrwcol0 cmemrwcol0
  301. private void
  302. cmemrwcol(rop_ptr rop)
  303. {
  304.     byte *dp = rop->dest;
  305.     const byte *sp = rop->src;
  306.     int yc = rop->height;
  307.     int shift = rop->shift;
  308.     byte invert = rop->invert;
  309.     int sraster = rop->sraster, draster = rop->draster;
  310.  
  311.     while (yc--) {
  312.     byte_discard(*dp);
  313.     *dp = ((*sp >> shift) + (*sp << (8 - shift))) ^ invert;
  314.     dp += draster, sp += sraster;
  315.     }
  316. }
  317. private void
  318. cmemrwcol0(rop_ptr rop)
  319. {
  320.     byte *dp = rop->dest;
  321.     const byte *sp = rop->src;
  322.     int yc = rop->height;
  323.     byte invert = rop->invert;
  324.     int sraster = rop->sraster, draster = rop->draster;
  325.  
  326.     if (yc > 0)
  327.     do {
  328.         byte_discard(*dp);
  329.         *dp = *sp ^ invert;
  330.         dp += draster, sp += sraster;
  331.     }
  332.     while (--yc);
  333. }
  334. #endif
  335.  
  336. #if USE_ASM
  337. void memrwcol2(P1(rop_ptr));    /* dest, draster, src, sraster, height, shift, invert */
  338. #else
  339. #define memrwcol2 cmemrwcol2
  340. private void
  341. cmemrwcol2(rop_ptr rop)
  342. {
  343.     byte *dp = rop->dest;
  344.     const byte *sp = rop->src;
  345.     int yc = rop->height;
  346.     int shift = rop->shift;
  347.     byte invert = rop->invert;
  348.     int sraster = rop->sraster, draster = rop->draster;
  349.  
  350.     while (yc--) {
  351.     byte_discard(*dp);
  352.     *dp = ((sp[1] >> shift) + (*sp << (8 - shift))) ^ invert;
  353.     dp += draster, sp += sraster;
  354.     }
  355. }
  356. #endif
  357.  
  358. /* Forward definitions */
  359. int ega_write_dot(P4(gx_device *, int, int, gx_color_index));
  360. private void fill_rectangle(P4(rop_ptr, int, int, int));
  361. private void fill_row_only(P4(byte *, int, int, int));
  362.  
  363. /* Clean up after writing */
  364. #define dot_end()\
  365.   set_g_mask(0xff)        /* all bits on */
  366.  
  367. /* Write a dot using the EGA color codes. */
  368. /* This doesn't have to be efficient. */
  369. int
  370. ega_write_dot(gx_device * dev, int x, int y, gx_color_index color)
  371. {
  372.     byte data[4];
  373.  
  374.     data[0] = (byte) color;
  375.     return ega_copy_color(dev, data, 1, 4, gx_no_bitmap_id, x, y, 1, 1);
  376. }
  377.  
  378. /* Macro for testing bit-inclusion */
  379. #define bit_included_in(x,y) !((x)&~(y))
  380.  
  381. /* Copy a monochrome bitmap.  The colors are given explicitly. */
  382. /* Color = gx_no_color_index means transparent (no effect on the image). */
  383. int
  384. ega_copy_mono(gx_device * dev,
  385.           const byte * base, int sourcex, int raster, gx_bitmap_id id,
  386.       int x, int y, int w, int h, gx_color_index izero, gx_color_index ione)
  387. {
  388.     rop_params params;
  389.  
  390. #define czero (int)izero
  391. #define cone (int)ione
  392.     int dleft, count;
  393.     byte mask, rmask;
  394.     fb_ptr save_dest;
  395.     int other_color = -1;
  396.  
  397.     fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
  398.     params.dest = mk_fb_ptr(x, y);
  399.     params.draster = fb_dev->raster;
  400.     params.src = base + (sourcex >> 3);
  401.     params.sraster = raster;
  402.     params.height = h;
  403.     params.shift = (x - sourcex) & 7;
  404.     /* Analyze the 16 possible cases: each of izero and ione may be */
  405.     /* 0, 0xf, transparent, or some other color. */
  406.     switch (czero) {
  407.     case no_color:
  408.         switch (cone) {
  409.         default:    /* (T, other) */
  410.             /* Must do 2 passes */
  411.             other_color = cone;
  412.             save_dest = params.dest;
  413.             /* falls through */
  414.         case 0:    /* (T, 0) */
  415.             set_g_function(gf_AND);
  416.             params.invert = -1;
  417.             break;
  418.         case 0xf:    /* (T, 0xf) */
  419.             set_g_function(gf_OR);
  420.             params.invert = 0;
  421.             break;
  422.         case no_color:    /* (T, T) */
  423.             return 0;    /* nothing to do */
  424.         }
  425.         break;
  426.     case 0:
  427.         params.invert = 0;
  428.         switch (cone) {
  429.         default:    /* (0, other) */
  430.             set_g_const(0);
  431.             set_g_const_map(cone ^ 0xf);
  432.             /* falls through */
  433.         case 0xf:    /* (0, 0xf) */
  434.             break;
  435.         case no_color:    /* (0, T) */
  436.             set_g_function(gf_AND);
  437.             break;
  438.         }
  439.         break;
  440.     case 0xf:
  441.         params.invert = -1;
  442.         switch (cone) {
  443.         case 0:    /* (0xf, 0) */
  444.             break;
  445.         default:    /* (0xf, other) */
  446.             set_g_const(0xf);
  447.             set_g_const_map(cone);
  448.             break;
  449.         case no_color:    /* (0xf, T) */
  450.             set_g_function(gf_OR);
  451.             /* falls through */
  452.         }
  453.         break;
  454.     default:
  455.         switch (cone) {
  456.         default:    /* (other, not T) */
  457.             if (bit_included_in(czero, cone)) {
  458.             set_g_const(czero);
  459.             set_g_const_map(czero ^ cone ^ 0xf);
  460.             params.invert = 0;
  461.             break;
  462.             } else if (bit_included_in(cone, czero)) {
  463.             set_g_const(cone);
  464.             set_g_const_map(cone ^ czero ^ 0xf);
  465.             params.invert = -1;
  466.             break;
  467.             }
  468.             /* No way around it, fill with one color first. */
  469.             save_dest = params.dest;
  470.             fill_rectangle((rop_ptr) & params, x & 7, w, cone);
  471.             params.dest = save_dest;
  472.             set_g_function(gf_XOR);
  473.             set_s_map(czero ^ cone);
  474.             other_color = -2;    /* must reset s_map at end */
  475.             params.invert = -1;
  476.             break;
  477.         case no_color:    /* (other, T) */
  478.             /* Must do 2 passes */
  479.             other_color = czero;
  480.             save_dest = params.dest;
  481.             set_g_function(gf_AND);
  482.             params.invert = 0;
  483.             break;
  484.         }
  485.         break;
  486.     }
  487.     /* Actually copy the bits. */
  488.     dleft = 8 - (x & 7);
  489.     mask = 0xff >> (8 - dleft);
  490.     count = w - dleft;
  491.     if (count < 0)
  492.     mask -= mask >> w,
  493.         rmask = 0;
  494.     else
  495.     rmask = 0xff00 >> (count & 7);
  496.     /* params: dest, src, sraster, height, shift, invert */
  497.     /* Smashes params.src, params.dest, count. */
  498.   copy:set_g_mask(mask);
  499.     if (params.shift == 0) {    /* optimize the aligned case *//* Do left column */
  500.     memrwcol0((rop_ptr) & params);
  501.     /* Do center */
  502.     if ((count -= 8) >= 0) {
  503.         out_g_mask(0xff);
  504.         do {
  505.         params.src++, params.dest++;
  506.         memrwcol0((rop_ptr) & params);
  507.         }
  508.         while ((count -= 8) >= 0);
  509.     }
  510.     /* Do right column */
  511.     if (rmask) {
  512.         params.src++, params.dest++;
  513.         out_g_mask(rmask);
  514.         memrwcol0((rop_ptr) & params);
  515.     }
  516.     } else {            /* Do left column */
  517.     int sleft = 8 - (sourcex & 7);
  518.  
  519.     if (sleft >= dleft) {    /* Source fits in one byte */
  520.         memrwcol((rop_ptr) & params);
  521.     } else if (w <= sleft) {    /* Source fits in one byte, thin case */
  522.         memrwcol((rop_ptr) & params);
  523.         goto fin;
  524.     } else {
  525.         memrwcol2((rop_ptr) & params);
  526.         params.src++;
  527.     }
  528.     /* Do center */
  529.     if ((count -= 8) >= 0) {
  530.         out_g_mask(0xff);
  531.         do {
  532.         params.dest++;
  533.         memrwcol2((rop_ptr) & params);
  534.         params.src++;
  535.         }
  536.         while ((count -= 8) >= 0);
  537.     }
  538.     /* Do right column */
  539.     if (rmask) {
  540.         out_g_mask(rmask);
  541.         params.dest++;
  542.         if (count + 8 <= params.shift)
  543.         memrwcol((rop_ptr) & params);
  544.         else
  545.         memrwcol2((rop_ptr) & params);
  546.     }
  547.     }
  548.   fin:if (other_color != -1) {
  549.     if (other_color >= 0) {    /* Do the second pass on (T, other) or (other, T). */
  550.         count = w - dleft;
  551.         params.src = base + (sourcex >> 3);
  552.         params.dest = save_dest;
  553.         params.invert ^= -1;
  554.         set_s_map(other_color);
  555.         set_g_function(gf_OR);
  556.         other_color = -2;
  557.         goto copy;
  558.     } else {        /* Finished second pass, restore s_map */
  559.         set_s_map(-1);
  560.     }
  561.     }
  562.     set_g_function(gf_WRITE);
  563.     set_g_const_map(0);
  564.     dot_end();
  565.     return 0;
  566. #undef czero
  567. #undef cone
  568. }
  569.  
  570. /* Copy a color pixelmap.  This is just like a bitmap, */
  571. /* except that each pixel takes 4 bits instead of 1. */
  572. int
  573. ega_copy_color(gx_device * dev,
  574.            const byte * base, int sourcex, int raster, gx_bitmap_id id,
  575.            int x, int y, int w, int h)
  576. {
  577.     const byte *line = base + (sourcex >> 1);
  578.     unsigned mask = 0x80 >> (x & 7);
  579.     int px = sourcex & 1;
  580.     fb_ptr fb_line;
  581.     int fb_raster = fb_dev->raster;
  582.  
  583.     fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
  584.     fb_line = mk_fb_ptr(x, y);
  585.     set_g_mode(gm_FILL);
  586.     select_g_mask();
  587.     for (;; px++) {
  588.     const byte *bptr = line;
  589.     fb_ptr fbptr = fb_line;
  590.     int py = h;
  591.  
  592.     out_g_mask(mask);
  593.     if (px & 1) {
  594.         do {
  595.         byte_discard(*fbptr);    /* latch frame buffer data */
  596.         *fbptr = *bptr;
  597.         bptr += raster;
  598.         fbptr += fb_raster;
  599.         }
  600.         while (--py);
  601.         line++;
  602.     } else {
  603.         do {
  604.         byte_discard(*fbptr);    /* latch frame buffer data */
  605.         *fbptr = *bptr >> 4;
  606.         bptr += raster;
  607.         fbptr += fb_raster;
  608.         }
  609.         while (--py);
  610.     }
  611.     if (!--w)
  612.         break;
  613.     if ((mask >>= 1) == 0)
  614.         mask = 0x80, fb_line++;
  615.     }
  616.     set_g_mode(gm_DATA);
  617.     dot_end();
  618.     return 0;
  619. }
  620.  
  621. /* Fill a rectangle. */
  622. int
  623. ega_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
  624.            gx_color_index color)
  625. {
  626.     rop_params params;
  627.  
  628.     fit_fill(dev, x, y, w, h);
  629.     params.dest = mk_fb_ptr(x, y);
  630.     if (h == 1)
  631.     fill_row_only(params.dest, x & 7, w, (int)color);
  632.     else {
  633.     params.draster = fb_dev->raster;
  634.     params.height = h;
  635.     fill_rectangle((rop_ptr) & params, x & 7, w, (int)color);
  636.     dot_end();
  637.     }
  638.     return 0;
  639. }
  640.  
  641. /* Tile a rectangle.  Note that the two colors must both be supplied, */
  642. /* i.e. neither one can be gx_no_color_index (transparent): */
  643. /* a transparent color means that the tile is colored, not a mask. */
  644. int
  645. ega_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
  646.       int x, int y, int w, int h, gx_color_index czero, gx_color_index cone,
  647.            int px, int py)
  648. #define zero (int)czero
  649. #define one (int)cone
  650. {
  651.     rop_params params;
  652.     int xmod, width_bytes;
  653.     int tile_height = tile->size.y;
  654.     int xbit;
  655.     int lcount;
  656.     int mask, rmask;
  657.     byte narrow;
  658.     byte again;
  659.     int const_bits, maps;
  660.     int ymod, yleft;
  661.  
  662.     fit_fill(dev, x, y, w, h);
  663.     /* We only handle the easiest cases directly. */
  664.     if ((tile->size.x & 7) || one == -1 || zero == -1 || px || py)
  665.     return gx_default_tile_rectangle(dev, tile, x, y, w, h,
  666.                      czero, cone, px, py);
  667.     /* Following is similar to aligned case of copy_mono */
  668.     params.dest = mk_fb_ptr(x, y);
  669.     params.draster = fb_dev->raster;
  670.     params.sraster = tile->raster;
  671.     params.shift = 0;
  672.     xbit = x & 7;
  673.     /* Set up the graphics registers */
  674.     const_bits = (zero ^ one) ^ 0xf;
  675.     if (const_bits) {
  676.     set_g_const(zero);    /* either color will do */
  677.     set_g_const_map(const_bits);
  678.     }
  679.     if ((maps = zero & ~one) != 0) {
  680.     set_s_map(maps += const_bits);
  681.     params.invert = -1;
  682.     again = one & ~zero;
  683.     } else {
  684.     maps = one & ~zero;
  685.     set_s_map(maps += const_bits);
  686.     params.invert = 0;
  687.     again = 0;
  688.     }
  689.     xmod = (x % tile->size.x) >> 3;
  690.     width_bytes = tile->size.x >> 3;
  691.     mask = 0xff >> xbit;
  692.     if (w + xbit <= 8)
  693.     mask -= mask >> w,
  694.         rmask = 0,
  695.         narrow = 1;
  696.     else {
  697.     rmask = (0xff00 >> ((w + x) & 7)) & 0xff;
  698.     if (xbit)
  699.         w += xbit - 8;
  700.     else
  701.         mask = 0, --xmod, --params.dest;
  702.     narrow = 0;
  703.     }
  704.     ymod = y % tile_height;
  705.   tile:yleft = tile_height - ymod;
  706.     params.src = tile->data + ymod * params.sraster + xmod;
  707.     lcount = h;
  708.     if (narrow) {        /* Optimize narrow case */
  709.     set_g_mask(mask);
  710.     if (lcount > yleft) {
  711.         params.height = yleft;
  712.         memrwcol0((rop_ptr) & params);
  713.         params.dest += yleft * params.draster;
  714.         params.src = tile->data + xmod;
  715.         params.height = tile_height;
  716.         lcount -= yleft;
  717.         while (lcount >= tile_height) {
  718.         memrwcol0((rop_ptr) & params);
  719.         params.dest += tile_height * params.draster;
  720.         lcount -= tile_height;
  721.         }
  722.     }
  723.     if (lcount) {
  724.         params.height = lcount;
  725.         memrwcol0((rop_ptr) & params);
  726.     }
  727.     } else {
  728.     fb_ptr line = params.dest;
  729.     int xpos = width_bytes - xmod;
  730.  
  731.     while (1) {
  732.         int xleft = xpos;
  733.         int count = w;
  734.  
  735.         params.height = (lcount > yleft ? yleft : lcount);
  736.         /* Do first byte, if not a full byte. */
  737.         if (mask) {
  738.         set_g_mask(mask);
  739.         memrwcol0((rop_ptr) & params);
  740.         }
  741.         /* Do full bytes */
  742.         if ((count -= 8) >= 0) {
  743.         set_g_mask(0xff);
  744.         do {
  745.             if (!--xleft)
  746.             xleft = width_bytes,
  747.                 params.src -= width_bytes;
  748.             ++params.src, ++params.dest;
  749.             memrwcol0((rop_ptr) & params);
  750.         }
  751.         while ((count -= 8) >= 0);
  752.         }
  753.         /* Do last byte */
  754.         if (rmask) {
  755.         if (!--xleft)
  756.             xleft = width_bytes,
  757.             params.src -= width_bytes;
  758.         set_g_mask(rmask);
  759.         ++params.src, ++params.dest;
  760.         memrwcol0((rop_ptr) & params);
  761.         }
  762.         if ((lcount -= params.height) == 0)
  763.         break;
  764.         params.dest = line += params.height * params.draster;
  765.         params.src = tile->data + xmod;
  766.         yleft = tile_height;
  767.     }
  768.     }
  769.     /* Now do the second color if needed */
  770.     if (again) {
  771.     maps = again + const_bits;
  772.     set_s_map(maps);
  773.     again = 0;
  774.     params.dest = mk_fb_ptr(x, y);
  775.     if (mask == 0)
  776.         params.dest--;
  777.     params.invert = 0;
  778.     goto tile;
  779.     }
  780.     if (maps != 0xf)
  781.     set_s_map(-1);
  782.     if (const_bits)
  783.     set_g_const_map(0);
  784.     dot_end();
  785.     return 0;
  786. }
  787.  
  788. /* Read scan lines back from the frame buffer. */
  789. int
  790. ega_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
  791. {                /* The maximum width for an EGA/VGA device is 800 pixels.... */
  792.     int width_bytes = (dev->width + 7) >> 3;
  793.     int i;
  794.     bits32 *dest;
  795.     const byte *src;
  796.     const byte *end;
  797.     byte planes[100 * 4];
  798.  
  799.     /* Plane 0 is the least significant plane. */
  800.     /* We know we're on a little-endian machine.... */
  801. #define spread4(v)\
  802.  v+0x00000000, v+0x08000000, v+0x80000000, v+0x88000000,\
  803.  v+0x00080000, v+0x08080000, v+0x80080000, v+0x88080000,\
  804.  v+0x00800000, v+0x08800000, v+0x80800000, v+0x88800000,\
  805.  v+0x00880000, v+0x08880000, v+0x80880000, v+0x88880000
  806.     static const bits32 spread8[256] =
  807.     {spread4(0x0000), spread4(0x0800),
  808.      spread4(0x8000), spread4(0x8800),
  809.      spread4(0x0008), spread4(0x0808),
  810.      spread4(0x8008), spread4(0x8808),
  811.      spread4(0x0080), spread4(0x0880),
  812.      spread4(0x8080), spread4(0x8880),
  813.      spread4(0x0088), spread4(0x0888),
  814.      spread4(0x8088), spread4(0x8888)
  815.     };
  816.  
  817.     if (y < 0 || y >= dev->height || dev->width > 800)
  818.     return_error(gs_error_rangecheck);
  819.     /* Read 4 planes into the holding buffer. */
  820.     for (i = 0; i < 4; ++i) {
  821.     set_g_read_plane(i);
  822.     memcpy(planes + 100 * i, mk_fb_ptr(0, y), width_bytes);
  823.     }
  824.     /* Now assemble the final data from the planes. */
  825.     for (dest = (bits32 *) data, src = planes, end = src + width_bytes;
  826.      src < end; ++dest, ++src
  827.     )
  828.     *dest = (((((spread8[src[0]] >> 1) | spread8[src[100]]) >> 1) |
  829.           spread8[src[200]]) >> 1) | spread8[src[300]];
  830.     if (actual_data != 0)
  831.     *actual_data = data;
  832.     return 0;
  833. }
  834.  
  835. /* ------ Internal routines ------ */
  836.  
  837. /* Mask table for rectangle fill. */
  838. static const byte rmask_tab[9] =
  839. {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
  840. };
  841.  
  842. /* Fill a rectangle specified by pointer into frame buffer, */
  843. /* starting bit within byte, width, and height. */
  844. /* Smashes rop->dest. */
  845. private void
  846. fill_rectangle(register rop_ptr rop, int bit, int w, int color)
  847.   /* rop: dest, draster, height */
  848. {
  849.     set_g_const(color);
  850.     set_g_const_map(0xf);
  851.     select_g_mask();
  852.     if (bit + w <= 8) {        /* Less than one byte */
  853.     out_g_mask(rmask_tab[w] >> bit);
  854.     memsetcol(rop);
  855.     } else {
  856.     byte right_mask;
  857.  
  858.     if (bit) {
  859.         out_g_mask(0xff >> bit);
  860.         memsetcol(rop);
  861.         rop->dest++;
  862.         w += bit - 8;
  863.     }
  864.     if (w >= 8) {
  865.         out_g_mask(0xff);    /* all bits */
  866.         rop->width = w >> 3;
  867.         memsetrect(rop);
  868.         rop->dest += rop->width;
  869.         w &= 7;
  870.     }
  871.     if ((right_mask = rmask_tab[w]) != 0) {
  872.         out_g_mask(right_mask);
  873.         memsetcol(rop);
  874.     }
  875.     }
  876.     set_g_const_map(0);
  877. }
  878.  
  879. /* Fill a single row specified by pointer into frame buffer, */
  880. /* starting bit within byte, and width; clean up afterwards. */
  881. #define r_m_w(ptr) (*(ptr))++    /* read & write, data irrelevant */
  882. private void
  883. fill_row_only(byte * dest, int bit, int w, int color)
  884.   /* rop: dest */
  885. {
  886.     if (bit + w <= 8) {        /* Less than one byte. */
  887.     /* Optimize filling with black or white. */
  888.     switch (color) {
  889.         case 0:
  890.         set_g_mask(rmask_tab[w] >> bit);
  891.         *dest &= color;    /* read, then write 0s; */
  892.         /* some compilers optimize &= 0 to a store. */
  893.         out_g_mask(0xff);    /* dot_end */
  894.         break;
  895.         case 0xf:
  896.         set_g_mask(rmask_tab[w] >> bit);
  897.         *dest |= 0xff;    /* read, then write 1s; */
  898.         /* some compilers optimize &= 0 to a store. */
  899.         out_g_mask(0xff);    /* dot_end */
  900.         break;
  901.         default:
  902.         set_g_const(color);
  903.         set_g_const_map(0xf);
  904.         set_g_mask(rmask_tab[w] >> bit);
  905.         r_m_w(dest);
  906.         out_g_mask(0xff);    /* dot_end */
  907.         set_g_const_map(0);
  908.     }
  909.     } else {
  910.     byte right_mask;
  911.     int byte_count;
  912.  
  913.     set_g_const(color);
  914.     set_g_const_map(0xf);
  915.     select_g_mask();
  916.     if (bit) {
  917.         out_g_mask(0xff >> bit);
  918.         r_m_w(dest);
  919.         dest++;
  920.         w += bit - 8;
  921.     }
  922.     byte_count = w >> 3;
  923.     if ((right_mask = rmask_tab[w & 7]) != 0) {
  924.         out_g_mask(right_mask);
  925.         r_m_w(dest + byte_count);
  926.     }
  927.     out_g_mask(0xff);
  928.     if (byte_count) {
  929.         memset(dest, 0, byte_count);    /* data irrelevant */
  930.     }
  931.     set_g_const_map(0);
  932.     }
  933. }
  934.